package com.ruoyi.framework.interceptor;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.ruoyi.common.annotation.ApiLogin;
import com.ruoyi.common.cont.MiniConst;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.LoginStudent;
import com.ruoyi.common.enums.RRExceptionCodeEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.concurrent.TimeUnit;

/**
 * ThirdSession拦截器
 * 校验每个请求的ThirdSession
 *
 * @author byChen
 * @date 2023/05/22
 */
@Component
public class ApiSessionInterceptorOld implements HandlerInterceptor {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 判断接口是否添加了需要携带session的注解 @MiniLogin
     * 以及请求是否携带sessionKey,并且判断session是否过期
     *
     * @param request  Request
     * @param response Response
     * @param handler  handler
     * @return 是否通行
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //判断静态资源放行
        if (handler instanceof HandlerMethod) {
            HandlerMethod method = (HandlerMethod) handler;
            //判断访问的control是否添加ApiLogin注解
            ApiLogin apiLogin = method.getMethodAnnotation(ApiLogin.class);
            String sessionKey = request.getHeader(MiniConst.SESSION_KEY);
            if (apiLogin != null && apiLogin.mustLogin()) {
                if (StrUtil.isNotBlank(sessionKey)) {
                    //获取缓存中的ThirdSession
                    String key = MiniConst.SESSION_BEGIN + ":" + sessionKey;
                    Object thirdSessionObj = redisTemplate.opsForValue().get(key);
                    //session过期
                    if (thirdSessionObj == null) {
                        ApiSessionHolder.clear();
                        AjaxResult r = AjaxResult.error(RRExceptionCodeEnum.API_TIME_OUT.getCode(), RRExceptionCodeEnum.API_TIME_OUT.getMessage());
                        this.writerPrint(response, r);
                        return Boolean.FALSE;
                    } else {
                        //不过期就存入全链路跟踪中
                        String thirdSessionStr = String.valueOf(thirdSessionObj);
                        LoginStudent loginStudent = JSONUtil.toBean(thirdSessionStr, LoginStudent.class);
                        ApiSessionHolder.setLoginStudent(loginStudent);
                        //刷新session剩余时长
                        redisTemplate.opsForValue().set(key,thirdSessionStr, MiniConst.SESSION_TIME_OUT, TimeUnit.HOURS);
                        return Boolean.TRUE;
                    }
                } else {
                    //没有携带session，返回提示
                    ApiSessionHolder.clear();
                    AjaxResult r = AjaxResult.error(RRExceptionCodeEnum.API_HAVE_NO_SESSION.getCode(), RRExceptionCodeEnum.API_HAVE_NO_SESSION.getMessage());
                    this.writerPrint(response, r);
                    return Boolean.FALSE;
                }
            }
            return Boolean.TRUE;
        } else {
            return Boolean.TRUE;
        }
    }

    /**
     * 向页面返回的
     *
     * @param response
     * @param r
     * @throws IOException
     */
    private void writerPrint(HttpServletResponse response, AjaxResult r) throws IOException {
        //返回超时错误码
        response.setCharacterEncoding("UTF-8");
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        PrintWriter writer = response.getWriter();
        writer.print(JSONUtil.parseObj(r));
        if (writer != null) {
            writer.close();
        }
    }
}
